from nevow import compy
from nevow import inevow
from nevow import tags
from nevow import rend
from nevow import loaders
from nevow import guard
import twisted.python.components

from activist.Event import Event
from activist.EventInformation import EventInformation
from activist.Person import Person
from activist.Place import Place
import activist.Place
from activist.Group import Group
from activist.Media import Media
from activist.MetaData import MetaData
from activist.Config import Config
from activist.Comment import Comment
from activist.DataStore import DataStore
from activist import Time
import activist.text
from activist.web.util import makeURL, makeRelative, addGetVariable

import time
import os.path
import exceptions
import urllib

class Message:
    "FIXME: total hack"
    def __init__(self,meta):
        self.meta = meta



class ISummaryView(compy.Interface):
    "Render a summary of an object."
class IMicroView(compy.Interface):
    "Render a minimal summary of an object."
class IFullView(compy.Interface):
    "Render the full view of an object."

class BaseFragment(rend.Fragment):

    def render_summaryview(self,context,data):
        try:
            return context.tag[tags.div(render=lambda ctx,data:ISummaryView(data),data=data)]
        except:
            if data is not None:
                return 'Cannot adapt %s to ISummaryView' % data.id()
            else:
                return 'Data is None for ISummaryView'
            
    def render_fullview(self,context,data):
        try:
            return context.tag[tags.div(render=lambda ctx,data:IFullView(data),data=data)]
        except TypeError:
            if data is not None:
                return 'Cannot adapt %s to ISummaryView' % data.id()
            else:
                return 'Data is None for ISummaryView'
    def render_microview(self,context,data):
        try:
            return context.tag[tags.div(render=lambda ctx,data:IMicroView(data),data=data)]
        except TypeError:
            if data is not None:
                return 'Cannot adapt %s to ISummaryView' % data.id()
            else:
                return 'Data is None for ISummaryView'
    

##
## comment
##

class CommentFragment(BaseFragment):
    def __init__(self,realdata):
        self.data = realdata
        BaseFragment.__init__(self)

    def render_subcomment(self,context,data):
        body = []
        for comment in self.data.comments():
            body.append(tags.div(render=lambda ctx,data:IFullView(data),data=comment))
        if len(body):
            return context.tag[body]
        return ''

    def render_comment(self, context, data):
        request = context.locate(inevow.IRequest)
        mind = request.session.mind
        uri = request.uri
        data = self.data
        showdata = data.isApproved()

        print "for comment",data.id(),"mind says",mind.showComment(data.id())
        if not showdata and mind.showComment(data.id()):
            showdata = True


        moderation = tags.div(_class="moderation")
        if not mind.isAnonymous() and mind.canModerate(data):
            showdata = True
            if data.isApproved():
                moderation[ tags.div(_class='moderation')[
                    tags.form(action=uri,method='post')[tags.input(_type='hidden',name='listingid',value=data.id()),
                                                        tags.input(_type='submit',name='unapprove',value='unapprove',_class='unapprove')],
                    tags.form(action=uri,method='post')[tags.input(_type='hidden',name='listingid',value=data.id()),
                                                        tags.input(_type='submit',name='delete',value='delete',_class='unapprove')]
                    ]]

            else:
                moderation[ tags.div(_class='moderation')[
                    tags.form(action=uri,method='post')[tags.input(_type='hidden',name='listingid',value=data.id()),
                                                        tags.input(_type='submit',name='approve',value='approve',_class='approve')],
                    tags.form(action=uri,method='post')[tags.input(_type='hidden',name='listingid',value=data.id()),
                                                        tags.input(_type='submit',name='delete',value='delete',_class='unapprove')]
                    ]]

        else:
            moderation = ''

        context.fillSlots( 'moderation', moderation )
        if data.creator():
            context.fillSlots( 'author', tags.a(href=makeRelative(request.uri,'/person/%s'%data.creator().id()))[data.creator().info()._name] )
        else:
            context.fillSlots( 'author', tags.span(_class="anonymous")['anonymous'] )

        if showdata:
            context.fillSlots( 'content', tags.p[data.content()] )
            reply = ''
            if request.session.mind.canComment(data):
                reply = tags.span(_class='participate',style='font-size:65%; margin-left:1em; padding:2px;')[
                    '[',tags.a(href=makeRelative(request.uri,'/create/comment?comment_on=%s'%data.id()))['reply'],']']
            context.fillSlots( 'reply', reply )
            if data.isApproved():
                context.fillSlots( 'title', tags.a(href=makeRelative(request.uri,'/comment/%s'%data.id()))[data.title()] )
            else:
                context.fillSlots( 'title', tags.a(href='?nocomment=%s'%data.id())[data.title()] )
        else:
            context.fillSlots( 'content', tags.p['This comment hasn\'t been approved; click its title to see it.'] )
            context.fillSlots( 'reply', '' )
            context.fillSlots( 'title', tags.a(href=addGetVariable(request.uri,'comment',data.id()))[data.title()] )


        if not data.isApproved():
            context.tag(_class="comment_unapproved")
        return context.tag

class CommentSummaryView(compy.Adapter):
    __implements__ = inevow.IRenderer, ISummaryView
    
    def __init__(self,original):
        compy.Adapter.__init__(self,original)
        class SummaryCommentFragment(CommentFragment):
            docFactory = loaders.htmlfile(Config.template('comment-summaryview.html'))

            def __init__(self,realdata):
                self.data = realdata
                CommentFragment.__init__(self)

            def render_comment(self, context, data):
                request = context.locate(inevow.IRequest)
                mind = request.session.mind
                uri = request.uri
                data = self.data
                showdata = data.isApproved()

                print "for comment",data.id(),"mind says",mind.showComment(data.id())
                if not showdata and mind.showComment(data.id()):
                    showdata = True
                    
                if showdata:
                    context.fillSlots( 'content', tags.p[data.content()] )
                    reply = ''
                    if request.session.mind.canComment(data):
                        reply = ['[',tags.a(href=makeRelative(request.uri,'/create/comment')+'?comment_on=%s'%data.id())['reply'],']']
                    context.fillSlots( 'reply', reply )
                    if data.isApproved():
                        context.fillSlots( 'title', tags.a(href=makeRelative(request.uri,'/comment/%s')%data.id())[data.title()] )
                    else:
                        context.fillSlots( 'title', tags.a(href=addGetVariable(request.uri,'nocomment',data.id()))[data.title()] )
                else:
                    context.fillSlots( 'content', tags.p['This comment hasn\'t been approved; click its title to see it.'] )
                    context.fillSlots( 'reply', '' )
                    context.fillSlots( 'title', tags.a(href=addGetVariable(request.uri,'comment',data.id()))[data.title()] )


                if not data.isApproved():
                    context.tag(_class="comment_unapproved")
                return context.tag
        self.fragment = SummaryCommentFragment(original)

    def rend(self,context,data):
        rtn = self.fragment.rend(context,data)
        return rtn[0].tag

compy.registerAdapter(CommentSummaryView, Comment, ISummaryView)


class CommentFullView(compy.Adapter):
    __implements__ = inevow.IRenderer, IFullView
    
    def __init__(self,original):
        compy.Adapter.__init__(self,original)
        self.fragment = CommentFragment(original)
        self.fragment.docFactory = loaders.htmlfile(Config.template('comment-fullview.html'))

    def rend(self,context,data):
        rtn = self.fragment.rend(context,data)
        return rtn[0].tag

compy.registerAdapter(CommentFullView, Comment, IFullView)


##
## event
##

class EventFragment(BaseFragment):
    def __init__(self,realdata):
        self.data = realdata
        BaseFragment.__init__(self)

    def render_listing(self, context, data):
        request = context.locate(inevow.IRequest)
        mind = request.session.mind
        uri = request.uri
        data = self.data

        if self.data.creator():
            context.fillSlots( 'creator', tags.a(href=makeRelative(request.uri,'/person') + '/%s'%self.data.creator().id())[str(self.data.creator().info()._name)] )
        else:
            context.fillSlots( 'creator', tags.span(_class='anonymous')['ANONYMOUS'] )
        numcomments = len(data.comments())
        if numcomments:
            if data.isApproved():
                content = [tags.a(href=makeRelative(request.uri,'/event') + '/%s'%data.id())[data.info().title()],
                           tags.span(_class='tiny')[' (%d comment threads)' % len(data.comments())]]
            else:
                content = ['unapproved: ',tags.a(href=makeRelative(request.uri,'/event')+'/%s'%data.id())[data.info().title()],
                           tags.span(_class='tiny')[' (%d comment threads)' % len(data.comments())]]

            context.fillSlots( 'title', content )

        else:
            bonus = ''
            if not data.isApproved():
                bonus = 'unapproved: '
            context.fillSlots( 'title', [bonus,tags.a(href=makeRelative(request.uri,'/event')+'/%s'%data.id())[data.info().title()]] )
        context.fillSlots( 'location', tags.div(render=lambda ctx,data:ISummaryView(data),data=data.info().where()) )
        context.fillSlots( 'when', self.when(data) )
        context.fillSlots( 'duration', self.duration(data) )
        context.fillSlots( 'eventtype', self.eventtype(data) )
        context.fillSlots( 'description', tags.p[data.info().brief()] )
        context.fillSlots( 'details', 'details' )

        if mind.canEdit(data):
            context.tag[ tags.div(_class='moderation')[
                tags.form(action=makeRelative(request.uri,'/create/event'),method='post')[tags.input(_type='hidden',name='edit',value=data.id()),
                                                                tags.input(_type='submit',name='_edit',value='edit',_class='edit')],
                
                tags.form(action=makeRelative(request.uri,'/event/time'),method='post')[tags.input(_type='hidden',name='listingid',value=data.id()),
                                                              tags.input(_type='submit',name='delete',value='delete',_class='edit')]
                ]]

        if not mind.isAnonymous() and mind.canModerate(data):
            if data.isApproved():
                context.tag[ tags.div(_class='moderation')[
                    tags.form(action=uri,method='post')[tags.input(_type='hidden',name='listingid',value=data.id()),
                                                        tags.input(_type='submit',name='unapprove',value='unapprove',_class='unapprove')]
                    ]]

            else:
                context.tag[ tags.div(_class='moderation')[
                    tags.form(action=uri,method='post')[tags.input(_type='hidden',name='listingid',value=data.id()),
                                                        tags.input(_type='submit',name='approve',value='approve',_class='approve')]
                    ]]

        if not data.isApproved():
            return tags.div(_class="unapproved")[context.tag]
        return context.tag

    def render_listingbody(self,context,data):
        request = context.locate(inevow.IRequest)
        mind = request.session.mind

        if self.data.creator():
            context.fillSlots( 'creator', tags.a(href=makeRelative(request.uri,'/person')+'/%s'%self.data.creator().id())[str(self.data.creator().info()._name)] )
        else:
            context.fillSlots( 'creator', tags.span(_class='anonymous')['ANONYMOUS'] )
        context.fillSlots( 'when', self.when(context) )
        context.fillSlots( 'duration', self.duration(data) )
        context.fillSlots( 'eventtype', self.eventtype(data) )

        approved = self.data.info().approvedBy()
        if not approved:
            context.fillSlots( 'approved', 'nobody' )
        else:
            context.fillSlots( 'approved', tags.a(href=makeRelative(request.uri,makeURL(request.uri, approved)))[approved.info().name()] )


        if not self.data.isApproved():
            context.tag(_class="listingbody_unapproved")
        else:
            context.tag(_class="listingbody")

# FIXME this should be only in one spot, not in this and the above method...
        if mind.canEdit(self.data):
            context.tag[ tags.div(_class='moderation')[
                tags.form(action=makeRelative(request.uri,'/create/event'),method='post')[tags.input(_type='hidden',name='edit',value=self.data.id()),
                                                                tags.input(_type='submit',name='edit',value='edit',_class='edit')],
                
                tags.form(action=makeRelative(request.uri,'/event/time'),method='post')[tags.input(_type='hidden',name='listingid',value=self.data.id()),
                                                              tags.input(_type='submit',name='delete',value='delete',_class='edit')]
                ]]

        if not mind.isAnonymous() and mind.canModerate(self.data):
            if self.data.isApproved():
                context.tag[ tags.div(_class='moderation')[
                    tags.form(action=request.uri,
                              method='post')[tags.input(_type='hidden',name='listingid',value=self.data.id()),
                                             tags.input(_type='submit',name='unapprove',value='unapprove',_class='unapprove')]
                    ]]

            else:
                context.tag[ tags.div(_class='moderation')[
                    tags.form(action=request.uri,
                              method='post')[tags.input(_type='hidden',name='listingid',value=self.data.id()),
                                             tags.input(_type='submit',name='approve',value='approve',_class='approve')]
                    ]]


        return context.tag

    def render_accessibility_inline(self,context,data):
        access = ['[',]
        for key in activist.EventInformation.ACCESSIBLE_KEYS:
            if key in self.data.info()._access:
                access = access + [tags.img(alt=activist.EventInformation.KEY_TO_DESCRIPTION[key],src=activist.EventInformation.KEY_TO_IMAGE[key]),', ']
            elif key in Config.inlineNegativeAccessibleKeys:
                access = access + [tags.img(alt=activist.EventInformation.KEY_TO_ANTIDESCRIPTION[key],src=activist.EventInformation.KEY_TO_ANTIIMAGE[key]),', ']
        access = access[:-1]            # remove trailing ', '
        return context.tag[access,']']

    def render_accessibility(self,context,data):
        access = []
        for key in activist.EventInformation.ACCESSIBLE_KEYS:
            if key in self.data.info()._access:
                access = access + [tags.li(_class=key)[tags.img(src=activist.EventInformation.KEY_TO_IMAGE[key]), '  ', activist.EventInformation.KEY_TO_DESCRIPTION[key]]]
            else:
                access = access + [tags.li(_class=key)[tags.img(src=activist.EventInformation.KEY_TO_ANTIIMAGE[key]), '  ', activist.EventInformation.KEY_TO_ANTIDESCRIPTION[key]]]
        return context.tag[tags.ul[access]]

    def render_unapprovedWarning(self,context,data):
        if self.data.isApproved():
            return ''
        return context.tag

    def render_makecomment(self,context,data):
        request = context.locate(inevow.IRequest)
        if request.session.mind.canComment(self.data):
            return context.tag
        return ''
        
    def render_reply(self,context,data):
        request = context.locate(inevow.IRequest)
        if request.session.mind.canComment(self.data):
            rest = '/create/comment?comment_on=%s'%(self.data.id(),)
            return context.tag(href=makeRelative(request.uri,rest))
        context.tag.clear()
        return context.tag

    def render_meta(self,context,data):
        context.fillSlots( 'creator', tags.span[ tags.a(href=makeRelative(request.uri,'/person')+'/%s'%self.data.creator().id())[self.data.creator().info()._name], tags.span['<' + self.data.creator().info()._email[0]+'>' ]] )
        return context.tag

    def render_title(self,context,data):
        context.tag[ self.data.info().title() ]
        return context.tag

    def render_comments(self,context,data):
        mind = inevow.IRequest(context).session.mind
        body = []
        if mind.option('summary-comments'):
            for comment in self.data.comments():
                body.append(tags.div(render=lambda ctx,data:ISummaryView(data),data=comment))
        else:
            for comment in self.data.comments():
                body.append(tags.div(render=lambda ctx,data:IFullView(data),data=comment))
        return context.tag[body]

    def duration(self, data):
        d = self.data.info().whenRaw()
        if isinstance(d,activist.Time.TimeRange):
            return ['...for ' + d.duration()]
        return ''

    def eventtype(self, data):
        return ['event-type: ',self.data.info()._type]
    
    def when(self, data):
        rtn = []
        rtn.append(self.data.info().when())

        if isinstance(self.data.info().whenRaw(),Time.Repeating):
            return rtn
        
        diff = self.data.info().whenRaw().diffFrom(time.time())
        if diff > 0.0:
            if diff > 86400:
                days = int(diff/86400)
                if days == 1:
                    rtn = rtn + [ ' ',tags.span(_class='date_delta')['[yesterday]'] ]
                elif days < 60:
                    rtn = rtn + [ ' ',tags.span(_class='date_delta')['[%d days ago]'%days] ]
                elif days < 365:
                    rtn = rtn + [ ' ',tags.span(_class='date_delta')['[%d weeks ago]'%(days/7)] ]
                else:
                    rtn = rtn + [ ' ',tags.span(_class='date_delta')['[%0.1f years ago]'%(days/365.0)] ]
            else:
                hours = int(diff/3600.0)
                rtn = rtn + [ ' ',tags.span(_class='date_delta')['[%d hours ago]'%hours] ]

        else:
            diff = -diff
            if diff > 86400:
                days = int(diff/86400)
                if days == 1:
                    rtn = rtn + [ ' ',tags.span(style='color:green;')['[tomorrow]'] ]
                else:
                    rtn = rtn + [ ' ',tags.span(style='color:green;')['[%d days from now]'%days] ]

            else:
                hours = int(diff/3600.0)
                rtn = rtn + [' ',tags.span(style='color:green;')['[%d hours from now!]'%hours]]

        return rtn

    def render_description(self,context,data):
        try:
            context.tag[tags.xml(activist.text.ToHTML(self.data.info().description()))]
        except exceptions.UnicodeEncodeError:
            return tags.div(_class='error')['Encoding problem.']

        ## FIXME TODO XXX use patterns like this elsewhere
        #edits = context.patternGenerator('edits')
        #editTag = edits(render=self.render_editedListing,data=self.data)

        return context.tag#[editTag]

    def render_locations(self,context,data):
        pattern = context.patternGenerator('location')
        stuff = pattern()[tags.div(render=lambda ctx,data:ISummaryView(data),data=self.data.info().where())]
        return context.tag[stuff]

    def render_contacts(self,context,data):
        pattern = context.tag.patternGenerator('contact')
        for contact in self.data.contacts():
            context.tag[pattern()[tags.div(render=lambda ctx,data:ISummaryView(data),data=contact)]]
        return context.tag

    def render_groups(self,context,data):
        body = []
        for group in self.data.groups():
            body.append(tags.div(render=lambda ctx,data:ISummaryView(data),data=group))
        return context.tag[body]

    def render_grouplogo(self,context,data):
        context.tag.clear()
        return ''


class EventSummaryView(compy.Adapter):
    __implements__ = inevow.IRenderer, ISummaryView

    def __init__(self,original):
        compy.Adapter.__init__(self,original)
        self.fragment = EventFragment(original)
        self.fragment.docFactory = loaders.htmlfile(Config.template('event-summary.html'))

    def rend(self,context,data):
        rtn = self.fragment.rend(context,data)
        return rtn[0].tag
    
compy.registerAdapter(EventSummaryView, Event, ISummaryView)


## event micro

class EventMicroView(compy.Adapter):
    __implements__ = inevow.IRenderer, IMicroView

    def __init__(self,original):
        compy.Adapter.__init__(self,original)
        self.fragment = EventFragment(original)
        self.fragment.docFactory = loaders.htmlfile(Config.template('event-micro.html'))

    def rend(self,context,data):
        rtn = self.fragment.rend(context,data)
        return rtn[0].tag
    
compy.registerAdapter(EventMicroView, Event, IMicroView)


## event full view

class EventFullView(compy.Adapter):
    __implements__ = inevow.IRenderer, IFullView

    def __init__(self,original):
        compy.Adapter.__init__(self,original)
        self.fragment = EventFragment(original)
        self.fragment.docFactory = loaders.htmlfile(Config.template('event-fullview.html'))


    def rend(self,context,data):
        rtn = self.fragment.rend(context,data)
        return rtn
    
compy.registerAdapter(EventFullView, Event, IFullView)


##
## Person views
##

class PersonFragment(BaseFragment):
    docFactory = None#loaders.htmlfile(os.path.join(Config.templatePath,'person-fullview.html'))

    def __init__(self,realdata):
        self.data = realdata
        BaseFragment.__init__(self)

    def render_owner(self, context, data):
        request = context.locate(inevow.IRequest)
        if request.session.mind.person() == self.data:
            context.tag(_class='participate')[tags.p['This is your page.']]
            ls = tags.ul
            if self.data.isAdministrator():
                ls = ls[tags.li['You are an administrator: ',tags.a(href=makeRelative(request.uri,'/admin'))['administration'],
                                ', ', tags.a(href=makeRelative(request.uri,'/create/article'))['create article'],
                                ', ', tags.a(href=makeRelative(request.uri,'/create/group'))['create group']
                                ]]
            if self.data.isModerator():
                ls = ls[tags.li['You are a moderator: ', tags.a(href=makeRelative(request.uri,'/help/moderators'))['moderator guide']]]
            if request.session.mind.canCreateMedia():
                ls = ls[tags.li['You may ', tags.a(href=makeRelative(request.uri,'/create/media'))['upload media'], '.']]
            if self.data.isCommentator():
                ls = ls[tags.li['You may create comments.']]
            else:
                ls = ls[tags.li['You cannot create comments. [',
                                tags.a(href=makeRelative(request.uri,'/help/comments'))['why not?'],
                                ']']
                        ]
            context.tag[ls]

            return context.tag
        return ''

    def render_bio(self, context, data):
        return context.tag[tags.xml(activist.text.ToHTML(self.data.info().bio()))]

    def render_messages(self, context, data):
        request = context.locate(inevow.IRequest)
        if True:
            if request.session.mind.isAnonymous() or \
               request.session.mind.person() != self.data:
                return ''

        context.tag[tags.h2['personal messages']]
        for meta in self.data.metadataTargetsForRelationship(MetaData.Message):
            context.tag[tags.div(render=lambda ctx,data:IFullView(data),data=Message(meta))]
        return context.tag

    def render_contributions(self, context, data):
        request = inevow.IRequest(context)
        things = self.data.metadataInverseTargetsForRelationship(MetaData.Creator)
        events = []
        comments = []
        metas = []
        media = []
        for x in things:
            if isinstance(x.fromData(),Event):
                events.append(x.fromData())
            elif isinstance(x.fromData(),Comment):
                comments.append(x.fromData())
            elif isinstance(x.fromData(),MetaData):
                metas.append(x.fromData())
            elif isinstance(x.fromData(),Media):
                media.append(x.fromData())

        if len(media):
            ets = []
            for m in media:
                ets.append(tags.a(href=makeURL(request.uri, m))[tags.img(alt=m._filename,src='/media/%s'%m.id(),height="120",width="120")])
            context.tag[ets]

        if len(events):
            ets = []
            for event in events:
                ets.append(tags.li[tags.a(href=makeRelative(request.uri,'/event/%s'%event.id()))[event.info().title()]])
            context.tag[tags.h3['Events'],tags.ul[ets]]

        if len(comments):
            ets = []
            for comment in comments:
                ets.append(tags.li[tags.a(href=makeRelative(request.uri,'/comment/%s'%comment.id()))[comment.title()]])
            context.tag[tags.h3['Comments'],tags.ul[ets]]

        format = "%b %d, %Y %H:%M"
        if len(metas):
            metas.sort(lambda x,y: -cmp(x.date(),y.date()))
            ets = []
            for meta in metas:
                if meta.relationship() == MetaData.BelongsWith and meta.toData() == DataStore.getGenericDataByTitle('moderated'):
                    d = meta.fromData()
                    if isinstance(d,Comment):
                        lnk = tags.a(href=makeRelative(request.uri,'/comment/%s'%d.id()))['comment: "%s"'%d.title()]
                    elif isinstance(d,EventInformation):
                        if d.event():
                            lnk = tags.a(href=makeRelative(request.uri,'/event/%s'%d.event().id()))[d.title()]
                        else:
                            if inevow.IRequest(context).session.mind.canAdmin():
                                lnk = tags.b["Orphan EventInformation with ID %s"%d.id()]
                            else:
                                lnk = tags.i["Edited ", tags.span(style="text-decoration:line-through;")[d.title()]]
                    else:
                        lnk = tags.a(href=makeRelative(request.uri,'/object/%s'%d.id()))[d.id()]
                    ets.append(tags.li[meta.formatDate(format), ' -- ',
                                       'Approved "',
                                       lnk,
                                       '".'])
                elif meta.relationship() == MetaData.BelongsWith and meta.toData() == DataStore.getGenericDataByTitle('administrator'):
                    ets.append(tags.li[meta.formatDate(format), ' -- ',
                                       'Made ',tags.a(href=makeURL(request.uri, meta.fromData()))[meta.fromData().info().name()],' an administrator'])
                elif meta.relationship() == MetaData.BelongsWith and meta.toData() == DataStore.getGenericDataByTitle('moderator'):
                    ets.append(tags.li[meta.formatDate(format), ' -- ',
                                       'Made ',tags.a(href=makeURL(request.uri, meta.fromData()))[meta.fromData().info().name()],' a moderator'])
                elif meta.relationship() == MetaData.BelongsWith and meta.toData() == DataStore.getGenericDataByTitle('commentator'):
                    ets.append(tags.li[meta.formatDate(format), ' -- ',
                                       'Allowed ',tags.a(href=makeURL(request.uri, meta.fromData()))[meta.fromData().info().name()],' to post comments.'])
                elif meta.relationship() == MetaData.InformationOf:
                    targ = meta.toData()
                    if isinstance(targ,Event):
                        ets.append(tags.li[meta.formatDate(format), ' -- ',
                                           'Edited ', tags.a(href=makeURL(request.uri, targ))[targ.info().title()]])
                    else:
                        ets.append(tags.li[meta.formatDate(format), ' -- ',
                                           'Edited ', tags.a(href=makeURL(request.uri, targ))[targ.info()._name]])
                        
                else:
                    ets.append(tags.li[meta.formatDate(format), ' -- ',
                                       tags.a(href=makeRelative(request.uri,'/object/%s'%meta.fromData().id()))[meta.fromData().id()],
                                       tags.span(style="font:70% sans-serif;")[' <--[%s]--> '%meta.relationship()],
                                       tags.a(href=makeRelative(request.uri,'/object/%s'%meta.toData().id()))[meta.toData().id()]])
            context.tag[tags.h3['MetaData'],tags.ul[ets]]

        return context.tag


    def data_phone(self, context, data):
        return self.data.info()._phone

    def data_email(self, context, data):
        rtn = []
        for address in self.data.info()._email:
            rtn.append( ' [at) '.join( ' [dot] '.join(address.split('.')).split('@') ) )
        return rtn

    def render_name(self, context, data):
        request = inevow.IRequest(context)
        return context.tag[tags.a(href=makeRelative(request.uri,'/person/%s'%self.data.id()))[self.data.info()._name]]

    def data_person(self, context, data):
        return self.data

    def render_phone(self, context, data):
        for x in self.data.info().phone():
            context.tag[x,' ']
        return context.tag

    def obfuscateEmail(self,email):
        (a,b) = email.split('@')
        return a + ' [at) ' + b
    def render_email(self, context, data):
        for x in self.data.info().email():
            try:
                context.tag[tags.a(href='javascript:window.location="mailto:%s" + "@" + "%s";'%tuple(x.split('@')))[self.obfuscateEmail(x)],
                        ' ']
            except TypeError:
                context.tag['invalid email:',tags.b[x]]
        return context.tag

    


## person summary 

class PersonSummaryView(compy.Adapter):
    __implements__ = inevow.IRenderer, ISummaryView

    def __init__(self,original):
        compy.Adapter.__init__(self,original)
        self.fragment = PersonFragment(original)
        self.fragment.docFactory = loaders.htmlfile(os.path.join(Config.templatePath,'person-summaryview.html'))

    def rend(self,context,data):
        rtn = self.fragment.rend(context,data)
        return rtn

compy.registerAdapter(PersonSummaryView, Person, ISummaryView)

## person full

class PersonFullView(compy.Adapter):
    __implements__ = inevow.IRenderer, IFullView

    def __init__(self,original):
        compy.Adapter.__init__(self,original)
        self.fragment = PersonFragment(original)
        self.fragment.docFactory = loaders.htmlfile(os.path.join(Config.templatePath,'person-fullview.html'))

    def rend(self,context,data):
        rtn = self.fragment.rend(context,data)
        return rtn
    
compy.registerAdapter(PersonFullView, Person, IFullView)



##
## Group views
##

class GroupFragment(BaseFragment):
    def __init__(self,realdata):
        self.data = realdata
        rend.Fragment.__init__(self)

    def render_description(self, context, data):
        return context.tag[tags.xml(activist.text.ToHTML(self.data.info()._description))]
        
    def render_contributions(self, context, data):
        request = inevow.IRequest(context)
        things = self.data.metadataInverseTargetsForRelationship(MetaData.Creator)
        events = []
        comments = []
        metas = []
        for x in things:
            if isinstance(x.fromData(),Event):
                events.append(x.fromData())
            elif isinstance(x.fromData(),Comment):
                comments.append(x.fromData())
            elif isinstance(x.fromData(),MetaData):
                metas.append(x.fromData())

        if len(events):
            ets = []
            for event in events:
                ets.append(tags.li[tags.a(href=makeRelative(request.uri,'/event/%s'%event.id()))[event.info().title()]])
            context.tag[tags.h3['Events'],tags.ul[ets]]

        if len(comments):
            ets = []
            for comment in comments:
                ets.append(tags.li[tags.a(href=makeRelative(request.uri,'/comment/%s'%comment.id()))[comment.title()]])
            context.tag[tags.h3['Comments'],tags.ul[ets]]

        if len(metas):
            ets = []
            for meta in metas:
                if meta.relationship() == MetaData.BelongsWith and meta.toData() == DataStore.getGenericDataByTitle('moderated'):
                    d = meta.fromData()
                    if isinstance(d,Comment):
                        lnk = tags.a(href=makeRelative(request.uri,'/comment/%s'%d.id()))['comment: "%s"'%d.title()]
                    elif isinstance(d,EventInformation):
                        lnk = tags.a(href=makeRelative(request.uri,'/event/%s'%d.event().id()))[d.title()]
                    else:
                        lnk = tags.a(href=makeURL(request.uri, d))[d.id()]
                    ets.append(tags.li['Approved "',
                                       lnk,
                                       '".'])
                else:
                    ets.append(tags.li[tags.a(href=makeRelative(request.uri,'/object/%s'%meta.fromData().id()))[meta.fromData().id()],
                                       tags.span(style="font:70% sans-serif;")[' <--[%s]--> '%meta.relationship()],
                                       tags.a(href=makeRelative(request.uri,'/object/%s'%meta.toData().id()))[meta.toData().id()]])
            context.tag[tags.h3['MetaData'],tags.ul[ets]]

        return context.tag

    def render_name(self, context, data):
        request = inevow.IRequest(context)
        return context.tag[tags.a(href=makeRelative(request.uri,'/group/%s'%self.data.id()))[self.data.info()._name]]

    def render_moderation(self, ctx, data):
        request = inevow.IRequest(ctx)
        mind = request.session.mind
        if mind.canEdit(self.data):
            ctx.tag[ tags.div(_class='moderation')[
                tags.form(action=makeRelative(request.uri,'/create/group'),method='post')[tags.input(_type='hidden',name='edit',value=self.data.id()),
                                                                tags.input(_type='submit',name='edit',value='edit',_class='edit')],
                ]]
            return ctx.tag
        return ''
    
    def render_people(self,context,data):
        if not hasattr(self,'_people'):
            self._people = self.data.people()

        rtn = context.tag
        request = inevow.IRequest(context)
        peeps = []
        
        for x in self._people:
            if request.session.mind.canAdmin() or request.session.mind.person() == x:
                form = tags.form(action=request.uri,method='post')[
                    tags.input(type='hidden',name='unjoingroup',value=x.id()),
                    tags.input(type='submit',name='unjoingroup',value='Leave Group')]
            else:
                form = ''
            peeps.append(tags.li[tags.span(render=lambda ctx,data:ISummaryView(data),data=x),form])

        join = ''
        if not request.session.mind.isAnonymous():
            if not request.session.mind.person() in self._people:
                join = tags.form(action=request.uri,method='post')[tags.input(_type='submit',name='joingroup',value='join this group',_class='edit')]
                

        return context.tag[tags.ul[peeps], join]

    def data_phone(self, context, data):
        return self.data.info()._phone

    def data_email(self, context, data):
        rtn = []
        for address in self.data.info()._email:
            rtn.append( ' [at) '.join( ' [dot] '.join(address.split('.')).split('@') ) )
        return rtn

    def data_group(self, context, data):
        return self.data

    def data_events(self,context,data):
        return self.data.events()
        


class GroupSummaryView(compy.Adapter):
    __implements__ = inevow.IRenderer, ISummaryView
    
    def __init__(self,original):
        compy.Adapter.__init__(self,original)
        self.fragment = GroupFragment(original)
        self.fragment.docFactory = loaders.htmlfile(os.path.join(Config.templatePath,'group-summaryview.html'))

    def rend(self,context,data):
        rtn = self.fragment.rend(context,data)
        return rtn
    
compy.registerAdapter(GroupSummaryView, Group, ISummaryView)


class GroupFullView(compy.Adapter):
    __implements__ = inevow.IRenderer, IFullView

    def __init__(self,original):
        compy.Adapter.__init__(self,original)
        self.fragment = GroupFragment(original)
        self.fragment.docFactory = loaders.htmlfile(Config.template('group-fullview.html'))

    def rend(self,context,data):
        rtn = self.fragment.rend(context,data)
        return rtn
    
compy.registerAdapter(GroupFullView, Group, IFullView)



##
## Place views
##

class PlaceFragment(BaseFragment):
    docFactory = None#loaders.htmlfile(os.path.join(Config.templatePath,'place-fullview.html'))

    def __init__(self,realdata):
        self.data = realdata
        BaseFragment.__init__(self)

    def data_name(self,context,data):
        return self.data._name

    def data_events(self,context,data):
        return self.data.events()

    def render_linked_name(self,ctx,data):
        request = inevow.IRequest(ctx)
        return ctx.tag[tags.a(href=makeURL(request.uri, self.data))[self.data._name]]
        return self.data._name

    def render_address_inline(self,context,data):
        addr = []
        for line in self.data._address.split('\n'):
            addr = addr + [tags.span[line]]
        if self.data._maplink:
            addr = addr + ['[',tags.a(href=self.data._maplink)['map'],']']
        return context.tag[addr]

    def render_location(self,context,data):
        addr = []
        for line in self.data._address.split('\n'):
            addr = addr + [tags.span[line],tags.br]
        if self.data._maplink:
            addr = addr + ['[',tags.a(href=self.data._maplink)['map'],']',tags.br]
        else:
            flataddress = ','.join(self.data._address.split('\n'))
            if self.data._address.count('\n') < 2:
                flataddress = flataddress + ',' + ','.join(self.data._locale.split('.'))
            addr = addr + ['[',tags.a(href='http://maps.google.com/maps?q='+urllib.quote_plus(flataddress))['googlemap'],']',tags.br]
        addr = addr + [self.data._phone,tags.br]
        return context.tag[addr]

    def render_notes(self, context, data):
        if not self.data._notes or self.data._notes == '':
            context.tag.clear()
            return context.tag

# FIXME TODO 
        return context.tag[self.data._notes]
        


## place summary 

class PlaceSummaryView(compy.Adapter):
    __implements__ = inevow.IRenderer, ISummaryView

    def __init__(self,original):
        compy.Adapter.__init__(self,original)
        self.fragment = PlaceFragment(original)
        self.fragment.docFactory = loaders.htmlfile(os.path.join(Config.templatePath,'place-summaryview.html'))

    def rend(self,context,data):
        rtn = self.fragment.rend(context,data)
        return rtn

compy.registerAdapter(PlaceSummaryView, Place, ISummaryView)

## place full

class PlaceFullView(compy.Adapter):
    __implements__ = inevow.IRenderer, IFullView

    def __init__(self,original):
        compy.Adapter.__init__(self,original)
        self.fragment = PlaceFragment(original)
        self.fragment.docFactory = loaders.htmlfile(os.path.join(Config.templatePath,'place-fullview.html'))

    def rend(self,context,data):
        rtn = self.fragment.rend(context,data)
        return rtn
    
compy.registerAdapter(PlaceFullView, Place, IFullView)







##
## Message
##

class MessageFragment(BaseFragment):
    def __init__(self,realdata):
        self.data = realdata
        BaseFragment.__init__(self)

    def render_message(self, context, data):
        request = context.locate(inevow.IRequest)
        mind = request.session.mind
        uri = request.uri
        data = self.data.meta

        print "RENDERING with ",data
        
        context.fillSlots( 'content', tags.xml(activist.text.ToHTML(data.toData().content())) )
        context.fillSlots( 'date', data.formatDate() )
        
        return context.tag



class MessageFullView(compy.Adapter):
    __implements__ = inevow.IRenderer, IFullView
    
    def __init__(self,original):
        compy.Adapter.__init__(self,original)
        self.fragment = MessageFragment(original)
        self.fragment.docFactory = loaders.htmlfile(Config.template('message-fullview.html'))

    def rend(self,context,data):
        rtn = self.fragment.rend(context,data)
        return rtn[0].tag

compy.registerAdapter(MessageFullView, Message, IFullView)


